﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;

namespace ETModel {
    [ObjectSystem]
    public class StartConfigComponentSystem1 : AwakeSystem<StartConfigComponent, string, int> {
        public override void Awake(StartConfigComponent self, string path, int appId) {
            self.Awake(string.Empty, path, appId);
        }
    }
    [ObjectSystem]
    public class StartConfigComponentSystem2 : AwakeSystem<StartConfigComponent, string, string, int> {
        public override void Awake(StartConfigComponent self, string clusterKey, string path, int appId) {
            self.Awake(clusterKey, path, appId);
        }
    }
    [ObjectSystem]
    public class StartConfigComponentSystem3 : AwakeSystem<StartConfigComponent, StartConfig> {
        public override void Awake(StartConfigComponent self, StartConfig startConfig) {
            self.Awake(string.Empty, startConfig);
        }
    }
    [ObjectSystem]
    public class StartConfigComponentSystem4 : AwakeSystem<StartConfigComponent, string, StartConfig> {
        public override void Awake(StartConfigComponent self, string clusterKey, StartConfig startConfig) {
            self.Awake(clusterKey, startConfig);
        }
    }

    /// <summary>
    /// 服务器配置组件,必须使用,定义当前实例的服务器类型,建议通过OptionComponent识别控制台输入配置来获得配置<para/>
    /// 可以指定配置文件生成:AddComponent&lt;StartConfigComponent, string, string, int&gt;(集群标识, 配置文件路径, 当前实例使用的appId)<para/>
    /// 也可以通过自行动态创建:AddComponent&lt;StartConfigComponent, string, StartConfig&gt;(集群标识, 手动创建的配置)<para/>
    /// </summary>
    public class StartConfigComponent : Component {
        public static StartConfigComponent Instance { get; private set; }

        private Dictionary<int, StartConfig> configDict;

        private Dictionary<int, IPEndPoint> innerAddressDict = new Dictionary<int, IPEndPoint>();

        public StartConfig StartConfig { get; private set; }

        public StartConfig DBConfig { get; private set; }

        public StartConfig RealmConfig { get; private set; }

        public StartConfig LocationConfig { get; private set; }

        public List<StartConfig> MapConfigs { get; private set; }

        public List<StartConfig> GateConfigs { get; private set; }

        public string ClusterKey { get; private set; }

        protected void AddStartConfig(StartConfig startConfig) {
            this.configDict.Add(startConfig.AppId, startConfig);

            InnerConfig innerConfig = startConfig.GetComponent<InnerConfig>();
            if (innerConfig != null) {
                this.innerAddressDict.Add(startConfig.AppId, innerConfig.IPEndPoint);
            }

            if (startConfig.AppType.Is(AppType.Realm)) {
                this.RealmConfig = startConfig;
            }

            if (startConfig.AppType.Is(AppType.Location)) {
                this.LocationConfig = startConfig;
            }

            if (startConfig.AppType.Is(AppType.DB)) {
                this.DBConfig = startConfig;
            }

            if (startConfig.AppType.Is(AppType.Map)) {
                this.MapConfigs.Add(startConfig);
            }

            if (startConfig.AppType.Is(AppType.Gate)) {
                this.GateConfigs.Add(startConfig);
            }
        }

        public void Awake(string clusterKey, StartConfig startConfig) {
            Instance = this;
            ClusterKey = clusterKey;

            this.configDict = new Dictionary<int, StartConfig>();
            this.MapConfigs = new List<StartConfig>();
            this.GateConfigs = new List<StartConfig>();

            try {
                AddStartConfig(startConfig);
            } catch (Exception e) {
                Log.Error($"config错误: {startConfig} {e}");
            }

            this.StartConfig = startConfig;
        }
        public void Awake(string clusterKey, string path, int appId) {
            Instance = this;
            ClusterKey = clusterKey;
            this.configDict = new Dictionary<int, StartConfig>();
            this.MapConfigs = new List<StartConfig>();
            this.GateConfigs = new List<StartConfig>();

            string[] ss = File.ReadAllText(path).Split('\n');
            foreach (string s in ss) {
                string s2 = s.Trim();
                if (s2 == "") {
                    continue;
                }
                try {
                    StartConfig startConfig = MongoHelper.FromJson<StartConfig>(s2);
                    AddStartConfig(startConfig);

                } catch (Exception e) {
                    Log.Error($"config错误: {s2} {e}");
                }
            }

            this.StartConfig = this.Get(appId);
        }

        public override void Dispose() {
            if (this.IsDisposed) {
                return;
            }
            base.Dispose();

            Instance = null;
        }

        public StartConfig Get(int id) {
            try {
                return this.configDict[id];
            } catch (Exception e) {
                throw new Exception($"not found startconfig: {id}", e);
            }
        }

        public IPEndPoint GetInnerAddress(int id) {
            try {
                return this.innerAddressDict[id];
            } catch (Exception e) {
                throw new Exception($"not found innerAddress: {id}", e);
            }
        }

        public StartConfig[] GetAll() {
            return this.configDict.Values.ToArray();
        }

        public int Count {
            get {
                return this.configDict.Count;
            }
        }
    }
}
